#include <string.h>
#include <unistd.h>

#include <atomic>
#include <cassert>
#include <condition_variable>  // std::condition_variable
#include <csignal>
#include <deque>
#include <functional>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>

#include "net_tcp.h"

namespace net {
using HeartBeatFunc = std::function<int(std::atomic_bool& b_thread_switch)>;
using RecvDataFunc  = std::function<int(std::atomic_bool& b_thread_switch, Socket*)>;
//客户端
class Client : public IOListener {
public:
    Client() : socket_sptr_(new net::Socket()), wait_fd_(epoll_create(1)) {}

    ~Client() {
        b_thread_switch_ = false;
        Close();
    }

    bool Connect(const std::string& ip, int port) {
        bool succ = socket_sptr_->Connect(ip, port);
        if (succ) {
            BindIO(socket_sptr_->ctx, IO_READ, this);  //! 我们只需要网络有数据来时通知
            ev_.events = EPOLLET | EPOLLRDHUP;
            ev_.events |= EPOLLIN;
            epoll_ctl(wait_fd_, EPOLL_CTL_ADD, socket_sptr_->ctx, &ev_);
            printf("Connect success.\n");
        }
        return succ;
    }

    void SetHeartBeatFunc(HeartBeatFunc f) {
        heartbeat_func_ = f;
    }

    void SetRecvDataFunc(RecvDataFunc f) {
        RecvData_func_ = f;
    }

    int GetRecv(char* buf, int& len) {
        assert(wait_fd_);
        if (epoll_wait(wait_fd_, &ev_, 1, 500) > 0) {
            if (ev_.events & EPOLLIN) {
                len = socket_sptr_->Recv(buf, len);
                return len;
            }
        }
        return 0;
    }
    bool GetHeartBeatStatus() {
        return socket_sptr_->GetHeartBeatStatus();
    }

    /// 实现数据可读时消息处理
    virtual void OnReadable() override {
        assert(RecvData_func_);
        RecvData_func_(b_thread_switch_, socket_sptr_.get());
    }

    void Close() {
        UnbindIO(socket_sptr_->ctx);  //! 关闭之前请取消IO事件监听
        socket_sptr_->Close();
        close(wait_fd_);
    }

    bool Send(const char* p, size_t s) {
        std::unique_lock<std::mutex> lck(send_mtx_);
        return socket_sptr_->Send(p, s);
    }

private:
    epoll_event             ev_;
    int                     wait_fd_{0};
    std::mutex              send_mtx_;
    std::shared_ptr<Socket> socket_sptr_;
    std::atomic_bool        b_thread_switch_{true};  //线程开关
    RecvDataFunc            RecvData_func_;          //数据接收回调
    HeartBeatFunc           heartbeat_func_;         //心跳回调
};

// int IgnoreSigpipe();
}  // namespace net